package game.engine.base.ui

import android.view.View

abstract  class UITween {

    var end = false  //  当前 end 结束
    var allEnd = false   // 整个tween链表结束
    var target: View? = null  // 指向下一个tween
    var nextTween: UITween? = null
    var headTween: UITween? = null

    abstract fun execute(dt: Float)
    open fun initialize(node: View){}

    fun runBy(pTarget: View,tweenMgr:UITweenManager) {

        val head = headTween!!
        head.target = pTarget

        // 当前tween 相当于tween链表的最后一个位置
        // 所以 需要找到当前 tween 链表的 head,然后加入到 tweenManager中,并且将target赋值给 表头
        // 将这个加入到  scene 的  tweenMgr中
//        val curScene = Director.instance.curScene!!
//        curScene.tweenManager.addTween(head)
        tweenMgr.addTween(head)
    }
}

class MoveBy(duration: Float, private val dx: Float, private val dy: Float) : MoveTo(duration, 0f, 0f) {
    override fun initialize(node: View) {
        cx = node.x
        cy = node.y
        dstX = node.x + dx
        dstY = node.y + dy
        px = dx / duration
        py = dy / duration
        elapsedTime = 0f
    }
}

open class MoveTo(val duration: Float, var dstX: Float, var dstY: Float) : UITween() {
    var firstExecute = false

    var px = 0f
    var py = 0f
    var cx = 0f
    var cy = 0f
    var elapsedTime = 0f

    init {
        headTween = this
    }

    override fun initialize(node: View) {
        cx = node.x
        cy = node.y
        px = (dstX - node.x) / duration
        py = (dstY - node.y) / duration
        elapsedTime = 0f
    }

    override fun execute(dt: Float) {
        val node = target!!
        if (!firstExecute) {
            initialize(node)
            firstExecute = true
        }

        elapsedTime += dt
        if (elapsedTime >= duration) {
            node.x = dstX
            node.y = dstY
            end = true
        } else {
            cx += px * dt
            cy += py * dt
            node.x = cx
            node.y = cy
        }
    }
}

open class RotateTo(val duration: Float, var dstDegress: Float) : UITween() {

    var firstExecute = false

    var px = 0f
    var cx = 0f
    var elapsedTime = 0f

    init {
        headTween = this
    }

    override fun initialize(node: View) {
        cx = node.rotation
        px = (dstDegress - node.rotation) / duration
        elapsedTime = 0f
    }

    override fun execute(dt: Float) {
        val node = target!!
        if (!firstExecute) {
            initialize(node)
            firstExecute = true
        }

        elapsedTime += dt
        if (elapsedTime >= duration) {
            node.rotation = dstDegress
            end = true
        } else {
            cx += px * dt
            node.rotation = cx
        }
    }

}

class RotateBy(duration: Float, val dxDegress: Float) : RotateTo(duration,0f) {
    override fun initialize(node: View) {
        cx = node.rotation
        dstDegress = dxDegress + cx
        px = dxDegress / duration
        elapsedTime = 0f
    }
}

open class ScaleTo(val duration: Float, var dstSx: Float, var dstSy: Float) : UITween() {
    var firstExecute = false

    var psx = 0f
    var psy = 0f
    var csx = 0f
    var csy = 0f
    var elapsedTime = 0f

    init {
        headTween = this
    }

    override fun initialize(node: View) {
        csx = node.scaleX
        csy = node.scaleY
        psx = (dstSx - csx) / duration
        psy = (dstSy - csy) / duration
        elapsedTime = 0f
    }

    override fun execute(dt: Float) {
        val node = target!!
        if (!firstExecute) {
            initialize(node)
            firstExecute = true
        }

        elapsedTime += dt
        if (elapsedTime >= duration) {
            node.scaleX = dstSx
            node.scaleY = dstSy
            end = true
        } else {
            csx += psx * dt
            csy += psy * dt
            node.scaleX = csx
            node.scaleY = csy
        }
    }

}

class ScaleBy( duration: Float,val dxSx:Float,val dxSy:Float):ScaleTo(duration,0f,0f){
    override fun initialize(node: View) {
        csx = node.scaleX
        csy = node.scaleY
        dstSx = csx * dxSx
        dstSy = csy * dxSy
        psx = dxSx / duration
        psy = dxSy / duration
        elapsedTime = 0f
    }
}

class Delay(val t: Float) : UITween() {
    var elapseTime = 0f

    init {
        headTween = this
    }

    override fun execute(dt: Float) {
        elapseTime += dt
        if (elapseTime >= t) {
            end = true
        }
    }
}

class Call(val action: (View) -> Unit) : UITween() {
    init {
        headTween = this
    }

    override fun execute(dt: Float) {
        action.invoke(target!!)
    }
}

//  并行
class Parallel(vararg tween: UITween): UITween(){

    val lst = ArrayList<UITween>()
    var firstExecute = false
    init {
        tween.forEach { lst.add(it) }
    }

    override fun initialize(node: View) {
        lst.forEach {
            it.target = node
            it.initialize(node)
        }
    }

    override fun execute(dt: Float) {
        val node = target!!
        if (!firstExecute) {
            initialize(node)
            firstExecute = true
        }

        for (i in lst.indices){
            val tween = lst[i]
            tween.execute(dt)
            if (tween.end){
                if (tween.nextTween == null){
                    tween.allEnd = true
                }else{
                    lst[i] = tween.nextTween!!
                    lst[i].target = node
                }
            }
        }

        // 删除已经执行完毕的
        val iter = lst.iterator()
        while (iter.hasNext()){
            val tween = iter.next()
            if (tween.allEnd){
                iter.remove()
            }
        }

        // 什么时候全部执行完毕?
        if (lst.size < 1){
            end = true
        }
    }
}